<?php

namespace app\api\model;

use app\api\service\WxPay;
use app\common\enums\StatusEnum;
use think\facade\Log;
use alipay\aop\AopClient;
use alipay\aop\request\AlipayTradeAppPayRequest;
use Alipay\aop\request\AlipayTradePagePayRequest;

class LangClass extends \app\common\model\LangClass
{
    
    const ALIPAY_TYPE = 1; //1支付宝支付类
    const WECHAT_TYPE = 2; //2微信支付类
    const APPLE_TYPE = 3; //苹果支付类型
    /**
     * 通过id查找班级信息，班级介绍页
     * @param int $langId 小语种id
     * @param int $type 班级类型，1初级班，2中级班，3高级班
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getOne($langId, $type)
    {
        $lang = Lang::getOne($langId);
        if (empty($lang)) {
            return [];
        }

        $model = static::field('id, content,money')
            ->where([
                'lang_id' => $langId,
                'type' => $type,
                'status' => StatusEnum::ENABLED
            ])->find();

        $result = [];
        if ($model) {
            $result = [
                'title' => $lang['name'] . self::attributes('type', $type),
                'langId' => $lang['id'],
                'langName' => $lang['name'],
                'langIcon' => config('file_prefix') . $lang['icon'],
                'classId' => $model['id'] ? (int)$model['id'] : 0,
                'course' => self::attributes('course', $type),
                'content' => $model['content'] ? $model['content'] : '',
                'money'=>$model['money']?$model['money']:'0.0',

            ];
        }

        return $result;
    }

    /**
     * 购买班级信息、教导主任、可抵扣积分、优惠券
     * @param $classId
     * @param $oauthInfo
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function buyInfo($classId, $oauthInfo)
    {
        // 通过班级id查找对应的班级信息和语种信息
        $class = self::getClass($classId);
        if (empty($class)) {
            return [
                'classAll' => [],
                'customers' => [],
                'reduceMoney' => 0,
                'coupon' => []
            ];
        }

        $langId = $class['langId'];

        // 获取该语种下面的所有班级
        $classAll = static::field('id AS classId, type, money')
            ->where(['lang_id' => $langId, 'status' => StatusEnum::ENABLED])
            ->order(['type' => 'asc'])
            ->select()
            ->toArray();
        foreach ($classAll as $key => $value) {
            $classAll[$key]['typeName'] = self::attributes('type', $value['type']);
        }

        // 客服列表
        $customers = CustomerService::getListAll();

        // 积分可抵扣的金额
        $reduceMoney = 0;
        if ($oauthInfo['integral'] > 0) {
            $reduceMoney = Config::getReduceMoney($oauthInfo['integral']);
        }

        // 优惠券
        $coupon = Coupon::getListAll($oauthInfo['id']);

        return [
            'classAll' => $classAll,
            'customers' => $customers,
            'reduceMoney' => $reduceMoney,
            'coupon' => $coupon
        ];
    }

    /**
     * 通过班级id获取班级信息和语种信息
     * @param $classId
     * @return array|\PDOStatement|string|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getClass($classId)
    {
        $model = static::field('c.id, c.type, c.money, l.id AS langId, l.name AS langName')
            ->alias('c')
            ->join('lang l', 'c.lang_id = l.id')
            ->where(['c.id' => $classId, 'c.status' => StatusEnum::ENABLED, 'l.status' => StatusEnum::ENABLED])
            ->find();
        $result = [];
        if ($model) {
            $result = $model->toArray();
        }
        return $result;
    }

    /**
     * 统一下单(小程序)
     * @param string $openid 支付用户
     * @param array $classData 班级信息数据
     * @param string $realMoney 实际支付金额
     * @param string $reduceMoney 积分抵扣金额
     * @param int $couponId 优惠券id
     * @param int $customerId 客服id
     * @param string $shareKey 分享出去的唯一key
     * @return array
     * @throws \Exception
     */
    public static function prepay($openid, $classData, $realMoney, $reduceMoney, $couponId, $customerId,$code, $shareKey)
    {
        // 总金额，单位为分
        $totalFee = $realMoney * 100;
        $notifyUrl = url('/pay/notify', '', true, true);
        $body = '购买' . $classData['className'];
        // 订单号
        $outTradeNo = OauthOrder::getOrderSn();

        // 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用String(128)，怕字段不够装，只能简写了
        $attach = [
            'cs' => $classData['classIdStr'], // 班级ids,多个英文逗号隔开
            'rm' => $reduceMoney, // 积分抵扣金额
            'cn' => $couponId, // 优惠券id
            'key' => $shareKey, // 用户的分享key
            'kf' => $customerId, // 客服id
            'code' => $code     //分享码
        ];

        // 0元支付，直接加订单
        if ($realMoney <= 0) {
            $totalFee = 0;
            return self::directPay($openid, $attach, $outTradeNo, $totalFee);
        } else {
            // 微信支付
            return self::wxPay($openid, $body, $attach, $outTradeNo, $totalFee, $notifyUrl);
        }
    }

    /**
     * 小于等于0元 直接支付
     * @param $openid
     * @param $attach
     * @param $outTradeNo
     * @param $totalFee
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function directPay($openid, $attach, $outTradeNo, $totalFee)
    {
        $encodeAttach = json_encode($attach);
        // 支付回调处理
        $payResult = OauthOrder::orderPaid($openid, $outTradeNo, $totalFee, $encodeAttach, '0元支付', $msg,null);
        if ($payResult === false) {
            $data = [
                'text' => '错误',
                'err_code_des' => $msg,
            ];
            $success = false;
        } else {
            $data = [];
            $success = true;
        }
        return ['success' => $success, 'data' => $data];
    }

    /**
     * 微信支付
     * @param $openid
     * @param $body
     * @param $attach
     * @param $outTradeNo
     * @param $totalFee
     * @param $notifyUrl
     * @return array
     * @throws \Exception
     */
    public static function wxPay($openid, $body, $attach, $outTradeNo, $totalFee, $notifyUrl)
    {
        $wxPay = new WxPay();
        $param = [
            'body' => $body,
            'attach' => json_encode($attach),
            'out_trade_no' => $outTradeNo,
            'total_fee' => $totalFee,
            'time_start' => date('YmdHis'),
            'time_expire' => date('YmdHis', time() + 3600),
            'notify_url' => $notifyUrl,
            'trade_type' => 'JSAPI',
            'openid' => $openid,
        ];

        // 统一下单
        $return = $wxPay->unifiedOrder($param);
        if ($return['return_code'] == 'SUCCESS' && $return['result_code'] == 'SUCCESS') {
            $timeStamp = time();
            $data = [
                'appId' => $return['appid'],
                'nonceStr' => $wxPay::getNonceStr(),
                'package' => 'prepay_id=' . $return['prepay_id'],
                'timeStamp' => "$timeStamp",
                'signType' => 'MD5',
            ];
            $sign = $wxPay->makeSign($data);
            $data['paySign'] = $sign;
            $success = true;
        } else {
            $data = [
                'text' => '错误',
                'err_code_des' => $return['err_code_des'],
            ];
            // 实时写入报错信息
            Log::write($return, 'wxPayUnifiedOrder');
            $success = false;
        }
        return [
            'success' => $success,
            'data' => $data
        ];
    }
    
/*
 * ================================2019-10-29==============================
 */    
    
    /**
     * 统一下单(app支付)
     * @param string $uid 支付用户
     * @param array $classData 班级信息数据
     * @param string $realMoney 实际支付金额
     * @param string $reduceMoney 积分抵扣金额
     * @param int $couponId 优惠券id
     * @param int $customerId 客服id
     * @param string $shareKey 分享出去的唯一key
     * @return array
     * @throws \Exception
     */
    public static function prepayApp($uid, $classData, $realMoney, $reduceMoney, $couponId, $customerId, $shareKey,$payType,$code)
    {
        // 总金额，单位为分
        $totalFee = $realMoney;
        $body = '购买' . $classData['className'];
        // 订单号
        $outTradeNo = OauthOrder::getOrderSn();
    
        // 附加数据，在查询API和支付通知中原样返回，可作为自定义参数使用String(128)，怕字段不够装，只能简写了
        $attach = [
            'cs' => $classData['classIdStr'], // 班级ids,多个英文逗号隔开
            'rm' => $reduceMoney, // 积分抵扣金额
            'cn' => $couponId, // 优惠券id
            'key' => $shareKey, // 用户的分享key
            'kf' => $customerId, // 客服id
            'code' => $code // 客服id
        ];

        $totalFee = round($totalFee,2);
        if ($realMoney <= 0) {
            $totalFee = 0;
            return self::directPay($uid, $attach, $outTradeNo, $totalFee);
        } else {
            //订单入库
            OauthOrder::insertOrderSn($uid, $totalFee, $couponId, $outTradeNo,$customerId,$payType,$code);

            switch ($payType){
                case self::ALIPAY_TYPE:
                    return self::aliAppPay($uid,$body, $attach, $outTradeNo, $totalFee);
                    break;
                case self::WECHAT_TYPE:
                    return self::wxAppPay($uid, $body, $attach, $outTradeNo, $totalFee);
                    break;
                case self::APPLE_TYPE:
                    $data = array(
                        'out_trade_no'=> $outTradeNo,
                        'attach' => json_encode($attach),
                        'notify_url'=> url('/api/applepay/notify', '', true, true)
                    );
                    return ['success' => true,'data' => $data];
                    break;
                default:
                    return self::aliAppPay($uid,$body, $attach, $outTradeNo, $totalFee);
                    break; 
            }
            
        }
    }
    
    
    /**
     * 微信app支付
     * @param $uid
     * @param $body
     * @param $attach
     * @param $outTradeNo
     * @param $totalFee
     * @param $notifyUrl
     * @return array
     * @throws \Exception
     */
    public static function wxAppPay($uid, $body, $attach, $outTradeNo, $totalFee)
    {
        $wxPay = new WxPay();
        $totalFee = $totalFee * 100;
        $notifyUrl = url('/api/pay/wxnotify', '', true, true);
        $param = [
            'body' => $body,
            'attach' => json_encode($attach),
            'out_trade_no' => $outTradeNo,
            'total_fee' => $totalFee,
            'time_start' => date('YmdHis'),
            'time_expire' => date('YmdHis', time() + 3600),
            'notify_url' => $notifyUrl,
            'trade_type' => 'APP'
            
        ];
    
        // 统一下单
        $return = $wxPay->unifiedOrder($param);
        if ($return['return_code'] == 'SUCCESS' && $return['result_code'] == 'SUCCESS') {
            $timeStamp = time();
            $data = [
                'partnerId' => $return['mch_id'],
                'appId' => $return['appid'],
                'nonceStr' => $wxPay::getNonceStr(),
                'prepayId' => $return['prepay_id'],
                'timeStamp' => "$timeStamp",
                'signType' => 'MD5',
                'package' => 'Sign=WXPay',
            ];
            $sign = $wxPay->makeSign($data);
            $data['paySign'] = $sign;
            $success = true;
        } else {
            $data = [
                'text' => '错误',
                'err_code_des' => $return['err_code_des'],
            ];
            // 实时写入报错信息
            Log::write($return, 'wxPayUnifiedOrder');
            $success = false;
        }
        return [
            'success' => $success,
            'data' => $data
        ];
    }
    
    /**
     * 支付宝app支付
     * @return array
     * @throws \Exception
     */
    public static function aliAppPay($uid,$body, $attach, $outTradeNo, $totalFee)
    {
        $aliPay = config('app.alipayconfig');
        $aop                = new AopClient();
        $aop->gatewayUrl    = $aliPay['gatewayUrl'];
        $aop->appId         = $aliPay['appid'];
        $aop->rsaPrivateKey = $aliPay['rsaPrivateKey'];
        $aop->apiVersion    = $aliPay['apiVersion'];
        $aop->postCharset   = $aliPay['charset'];
        $aop->format        = $aliPay['format'];
        $aop->signType      = $aliPay['signType'];
        $request            = new AlipayTradeAppPayRequest();
    
        $data = array(
            'body'            => $body,
            'subject'         => $body,
            'out_trade_no'    => $outTradeNo,
            'total_amount'    => $totalFee,
            'timeout_express' => $aliPay['timeout_express'],
            'product_code'    => $aliPay['product_code'],
            'passback_params'=>urlencode(json_encode($attach))
        );
        $notifyUrl = url('/api/pay/alinotify', '', true, true);
        $request->setNotifyUrl($notifyUrl);
        $request->setReturnUrl($aliPay['callbackUrl']);
        $request->setBizContent(json_encode($data));
    
        $result = $aop->sdkExecute ( $request);
        return [
            'success' =>true,
            'data' => $result
        ];
    
    }
    
    
    

}